using System;
using System.Collections.Generic;
using GomokuGame.AI;

namespace GomokuGame
{
    /// <summary>
    /// 棋子类型枚举
    /// </summary>
    public enum PieceType
    {
        Empty = 0,
        Black = 1,
        White = 2
    }

    /// <summary>
    /// 游戏状态枚举
    /// </summary>
    public enum GameState
    {
        NotStarted,
        Playing,
        BlackWin,
        WhiteWin,
        Draw,
        Paused
    }

    /// <summary>
    /// 游戏模式枚举
    /// </summary>
    public enum GameMode
    {
        HumanVsHuman,
        HumanVsAI,
        AIVsAI
    }

    /// <summary>
    /// 五子棋游戏引擎
    /// </summary>
    public class GameEngine
    {
        private const int BOARD_SIZE = 15;
        private PieceType[,] board;
        private GameState currentState;
        private GameMode gameMode;
        private PieceType currentPlayer;
        private List<Move> moveHistory;
        private int maxUndoCount;
        private int currentUndoCount;
        
        // AI相关字段
        private AIManager aiManager;
        private AIDifficulty aiDifficulty;
        private PieceType aiPlayer; // AI执子颜色
        
        // 游戏记录相关字段
        private GameRecordManager recordManager;

        /// <summary>
        /// 棋盘大小
        /// </summary>
        public int BoardSize => BOARD_SIZE;

        /// <summary>
        /// 当前游戏状态
        /// </summary>
        public GameState CurrentState => currentState;

        /// <summary>
        /// 当前玩家
        /// </summary>
        public PieceType CurrentPlayer => currentPlayer;

        /// <summary>
        /// 游戏模式
        /// </summary>
        public GameMode GameMode => gameMode;

        /// <summary>
        /// 移动历史
        /// </summary>
        public IReadOnlyList<Move> MoveHistory => moveHistory.AsReadOnly();

        /// <summary>
        /// 当前悔棋次数
        /// </summary>
        public int CurrentUndoCount => currentUndoCount;

        /// <summary>
        /// 设置最大悔棋次数
        /// </summary>
        public int MaxUndoCount
        {
            get => maxUndoCount;
            set => maxUndoCount = value;
        }

        /// <summary>
        /// 游戏开始事件
        /// </summary>
        public event EventHandler<GameEventArgs> GameStarted;

        /// <summary>
        /// 棋子落子事件
        /// </summary>
        public event EventHandler<MoveEventArgs> PiecePlaced;

        /// <summary>
        /// 游戏结束事件
        /// </summary>
        public event EventHandler<GameEventArgs> GameEnded;

        /// <summary>
        /// 玩家切换事件
        /// </summary>
        public event EventHandler<PlayerChangedEventArgs> PlayerChanged;

        /// <summary>
        /// AI思考进度变化事件
        /// </summary>
        public event EventHandler<AIThinkingProgressEventArgs> AIThinkingProgressChanged;

        /// <summary>
        /// AI移动完成事件
        /// </summary>
        public event EventHandler<AIMoveCompletedEventArgs> AIMoveCompleted;

        /// <summary>
        /// 悔棋事件
        /// </summary>
        public event EventHandler<MoveEventArgs> PieceRemoved;

        public GameEngine()
        {
            InitializeGame();
            aiManager = new AIManager();
            
            // 绑定AI事件
            aiManager.ThinkingProgressChanged += OnAIThinkingProgressChanged;
            aiManager.MoveCompleted += OnAIMoveCompleted;
            
            // 初始化游戏记录管理器
            recordManager = new GameRecordManager();
        }

        /// <summary>
        /// 初始化游戏
        /// </summary>
        private void InitializeGame()
        {
            board = new PieceType[BOARD_SIZE, BOARD_SIZE];
            moveHistory = new List<Move>();
            currentState = GameState.NotStarted;
            currentPlayer = PieceType.Black;
            maxUndoCount = 3;
            currentUndoCount = 0;

            // 清空棋盘
            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    board[i, j] = PieceType.Empty;
                }
            }
        }

        /// <summary>
        /// 开始新游戏
        /// </summary>
        /// <param name="mode">游戏模式</param>
        public void StartNewGame(GameMode mode)
        {
            StartNewGame(mode, AIDifficulty.Intermediate, PieceType.White);
        }

        /// <summary>
        /// 开始新游戏（带AI参数）
        /// </summary>
        /// <param name="mode">游戏模式</param>
        /// <param name="aiDifficulty">AI难度</param>
        /// <param name="aiPlayer">AI执子颜色</param>
        public void StartNewGame(GameMode mode, AIDifficulty aiDifficulty, PieceType aiPlayer)
        {
            InitializeGame();
            gameMode = mode;
            currentState = GameState.Playing;
            currentPlayer = PieceType.Black;
            
            // 设置AI参数
            this.aiDifficulty = aiDifficulty;
            this.aiPlayer = aiPlayer;
            
            if (mode == GameMode.HumanVsAI || mode == GameMode.AIVsAI)
            {
                // 在AIVsAI模式下，为不同玩家设置不同的AI难度
                if (mode == GameMode.AIVsAI)
                {
                    // 黑方使用指定难度，白方使用稍低的难度
                    var blackAIDifficulty = aiDifficulty;
                    var whiteAIDifficulty = aiDifficulty == AIDifficulty.Beginner ? AIDifficulty.Beginner :
                                          aiDifficulty == AIDifficulty.Intermediate ? AIDifficulty.Beginner :
                                          aiDifficulty == AIDifficulty.Advanced ? AIDifficulty.Intermediate :
                                          AIDifficulty.Advanced;
                    
                    aiManager.SetAIDifficulty(blackAIDifficulty);
                    // 注意：这里我们暂时使用同一个AI管理器，但会在移动时动态调整策略
                }
                else
                {
                    aiManager.SetAIDifficulty(aiDifficulty);
                }
            }
            
            // 开始游戏记录
            recordManager.StartNewGameRecord(mode, aiDifficulty, aiPlayer);

            GameStarted?.Invoke(this, new GameEventArgs { GameState = currentState });
            PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { CurrentPlayer = currentPlayer });
            
            // 如果是AI vs AI模式，或者AI执黑，则开始AI回合
            if (mode == GameMode.AIVsAI || (mode == GameMode.HumanVsAI && aiPlayer == PieceType.Black))
            {
                StartAITurn();
            }
        }

        /// <summary>
        /// 在指定位置落子
        /// </summary>
        /// <param name="row">行坐标</param>
        /// <param name="col">列坐标</param>
        /// <returns>是否成功落子</returns>
        public bool PlacePiece(int row, int col)
        {
            if (currentState != GameState.Playing)
                return false;

            if (!IsValidPosition(row, col) || board[row, col] != PieceType.Empty)
                return false;

            // 检查是否是AI回合
            if (IsAITurn())
            {
                return false; // AI回合时不允许玩家落子
            }

            // 落子
            board[row, col] = currentPlayer;
            Move move = new Move(row, col, currentPlayer);
            moveHistory.Add(move);
            
            // 记录移动
            recordManager.RecordMove(row, col, currentPlayer);

            // 触发落子事件
            PiecePlaced?.Invoke(this, new MoveEventArgs { Move = move });

            // 检查胜负
            if (CheckWin(row, col, currentPlayer))
            {
                currentState = currentPlayer == PieceType.Black ? GameState.BlackWin : GameState.WhiteWin;
                recordManager.EndGameRecord(currentPlayer, "五子连线");
                GameEnded?.Invoke(this, new GameEventArgs { GameState = currentState });
                return true;
            }

            // 检查平局
            if (IsBoardFull())
            {
                currentState = GameState.Draw;
                recordManager.EndGameRecord(PieceType.Empty, "", true);
                GameEnded?.Invoke(this, new GameEventArgs { GameState = currentState });
                return true;
            }

            // 切换玩家
            SwitchPlayer();
            
            // 如果下一个是AI回合，则开始AI思考
            if (IsAITurn())
            {
                StartAITurn();
            }
            
            return true;
        }

        /// <summary>
        /// 获取指定位置的棋子类型
        /// </summary>
        /// <param name="row">行坐标</param>
        /// <param name="col">列坐标</param>
        /// <returns>棋子类型</returns>
        public PieceType GetPiece(int row, int col)
        {
            if (!IsValidPosition(row, col))
                return PieceType.Empty;

            return board[row, col];
        }

        /// <summary>
        /// 悔棋
        /// </summary>
        /// <returns>是否成功悔棋</returns>
        public bool Undo()
        {
            if (moveHistory.Count == 0 || currentUndoCount >= maxUndoCount)
                return false;

            Move lastMove = moveHistory[moveHistory.Count - 1];
            board[lastMove.Row, lastMove.Col] = PieceType.Empty;
            moveHistory.RemoveAt(moveHistory.Count - 1);
            currentUndoCount++;

            // 切换回上一个玩家
            SwitchPlayer();

            // 触发悔棋事件
            PieceRemoved?.Invoke(this, new MoveEventArgs { Move = lastMove });

            return true;
        }

        /// <summary>
        /// 重新开始游戏
        /// </summary>
        public void Restart()
        {
            StartNewGame(gameMode);
        }

        /// <summary>
        /// 暂停游戏
        /// </summary>
        public void Pause()
        {
            if (currentState == GameState.Playing)
            {
                currentState = GameState.Paused;
            }
        }

        /// <summary>
        /// 继续游戏
        /// </summary>
        public void Resume()
        {
            if (currentState == GameState.Paused)
            {
                currentState = GameState.Playing;
                
                // 如果当前是AI回合，则继续AI思考
                if (IsAITurn())
                {
                    StartAITurn();
                }
            }
        }

        /// <summary>
        /// 检查位置是否有效
        /// </summary>
        /// <param name="row">行坐标</param>
        /// <param name="col">列坐标</param>
        /// <returns>是否有效</returns>
        private bool IsValidPosition(int row, int col)
        {
            return row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE;
        }

        /// <summary>
        /// 切换玩家
        /// </summary>
        private void SwitchPlayer()
        {
            currentPlayer = currentPlayer == PieceType.Black ? PieceType.White : PieceType.Black;
            PlayerChanged?.Invoke(this, new PlayerChangedEventArgs { CurrentPlayer = currentPlayer });
        }

        /// <summary>
        /// 检查是否获胜
        /// </summary>
        /// <param name="row">行坐标</param>
        /// <param name="col">列坐标</param>
        /// <param name="pieceType">棋子类型</param>
        /// <returns>是否获胜</returns>
        private bool CheckWin(int row, int col, PieceType pieceType)
        {
            // 检查横向
            if (CountInDirection(row, col, 0, 1, pieceType) + CountInDirection(row, col, 0, -1, pieceType) - 1 >= 5)
                return true;

            // 检查纵向
            if (CountInDirection(row, col, 1, 0, pieceType) + CountInDirection(row, col, -1, 0, pieceType) - 1 >= 5)
                return true;

            // 检查主对角线
            if (CountInDirection(row, col, 1, 1, pieceType) + CountInDirection(row, col, -1, -1, pieceType) - 1 >= 5)
                return true;

            // 检查副对角线
            if (CountInDirection(row, col, 1, -1, pieceType) + CountInDirection(row, col, -1, 1, pieceType) - 1 >= 5)
                return true;

            return false;
        }

        /// <summary>
        /// 在指定方向上计算连续棋子数量
        /// </summary>
        /// <param name="row">起始行</param>
        /// <param name="col">起始列</param>
        /// <param name="deltaRow">行方向增量</param>
        /// <param name="deltaCol">列方向增量</param>
        /// <param name="pieceType">棋子类型</param>
        /// <returns>连续棋子数量</returns>
        private int CountInDirection(int row, int col, int deltaRow, int deltaCol, PieceType pieceType)
        {
            int count = 0;
            int currentRow = row;
            int currentCol = col;

            while (IsValidPosition(currentRow, currentCol) && board[currentRow, currentCol] == pieceType)
            {
                count++;
                currentRow += deltaRow;
                currentCol += deltaCol;
            }

            return count;
        }

        /// <summary>
        /// 检查棋盘是否已满
        /// </summary>
        /// <returns>是否已满</returns>
        private bool IsBoardFull()
        {
            for (int i = 0; i < BOARD_SIZE; i++)
            {
                for (int j = 0; j < BOARD_SIZE; j++)
                {
                    if (board[i, j] == PieceType.Empty)
                        return false;
                }
            }
            return true;
        }

        #region AI相关方法

        /// <summary>
        /// 检查当前是否是AI回合
        /// </summary>
        /// <returns>是否是AI回合</returns>
        public bool IsAITurn()
        {
            if (gameMode == GameMode.HumanVsHuman)
                return false;

            if (gameMode == GameMode.AIVsAI)
                return true;

            if (gameMode == GameMode.HumanVsAI)
                return currentPlayer == aiPlayer;

            return false;
        }

        /// <summary>
        /// 开始AI回合
        /// </summary>
        private void StartAITurn()
        {
            if (!IsAITurn() || currentState != GameState.Playing)
                return;

            try
            {
                aiManager.StartAITurn(board, currentPlayer);
            }
            catch (Exception ex)
            {
                // AI出错时，可以选择随机落子或者跳过
                Console.WriteLine($"AI思考出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 停止AI回合
        /// </summary>
        public void StopAITurn()
        {
            aiManager.StopAITurn();
        }

        /// <summary>
        /// 设置AI难度
        /// </summary>
        /// <param name="difficulty">AI难度</param>
        public void SetAIDifficulty(AIDifficulty difficulty)
        {
            aiDifficulty = difficulty;
            aiManager.SetAIDifficulty(difficulty);
        }

        /// <summary>
        /// 获取当前AI难度
        /// </summary>
        /// <returns>AI难度</returns>
        public AIDifficulty GetAIDifficulty()
        {
            return aiDifficulty;
        }

        /// <summary>
        /// 获取AI玩家颜色
        /// </summary>
        /// <returns>AI执子颜色</returns>
        public PieceType GetAIPlayer()
        {
            return aiPlayer;
        }

        /// <summary>
        /// 获取AI管理器
        /// </summary>
        /// <returns>AI管理器</returns>
        public AIManager GetAIManager()
        {
            return aiManager;
        }
        
        #region 游戏记录相关方法
        
        /// <summary>
        /// 获取游戏记录管理器
        /// </summary>
        /// <returns>游戏记录管理器</returns>
        public GameRecordManager GetRecordManager()
        {
            return recordManager;
        }
        
        /// <summary>
        /// 保存当前游戏记录
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns>保存的文件路径</returns>
        public string SaveGameRecord(string fileName = null)
        {
            return recordManager.SaveCurrentGameRecord(fileName);
        }
        
        /// <summary>
        /// 导出当前游戏记录为SGF格式
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>SGF内容</returns>
        public string ExportToSGF(string filePath = null)
        {
            return recordManager.ExportToSGF(filePath);
        }
        
        #endregion

        #endregion

        #region AI事件处理

        /// <summary>
        /// AI思考进度变化事件处理
        /// </summary>
        /// <param name="sender">事件源</param>
        /// <param name="e">事件参数</param>
        private void OnAIThinkingProgressChanged(object sender, AIThinkingProgressEventArgs e)
        {
            AIThinkingProgressChanged?.Invoke(this, e);
        }

        /// <summary>
        /// AI移动完成事件处理
        /// </summary>
        /// <param name="sender">事件源</param>
        /// <param name="e">事件参数</param>
        private void OnAIMoveCompleted(object sender, AIMoveCompletedEventArgs e)
        {
            if (currentState != GameState.Playing || !IsAITurn())
                return;

            // 执行AI的移动
            var aiMove = e.Move;
            if (IsValidPosition(aiMove.Row, aiMove.Col) && board[aiMove.Row, aiMove.Col] == PieceType.Empty)
            {
                // 落子
                board[aiMove.Row, aiMove.Col] = currentPlayer;
                Move move = new Move(aiMove.Row, aiMove.Col, currentPlayer);
                moveHistory.Add(move);
                
                // 记录AI移动
                recordManager.RecordMove(aiMove.Row, aiMove.Col, currentPlayer);

                // 触发落子事件
                PiecePlaced?.Invoke(this, new MoveEventArgs { Move = move });

                // 检查胜负
                if (CheckWin(aiMove.Row, aiMove.Col, currentPlayer))
                {
                    currentState = currentPlayer == PieceType.Black ? GameState.BlackWin : GameState.WhiteWin;
                    recordManager.EndGameRecord(currentPlayer, "五子连线");
                    GameEnded?.Invoke(this, new GameEventArgs { GameState = currentState });
                    return;
                }

                // 检查平局
                if (IsBoardFull())
                {
                    currentState = GameState.Draw;
                    recordManager.EndGameRecord(PieceType.Empty, "", true);
                    GameEnded?.Invoke(this, new GameEventArgs { GameState = currentState });
                    return;
                }

                // 切换玩家
                SwitchPlayer();

                // 如果是AI vs AI模式，继续下一个AI回合
                if (gameMode == GameMode.AIVsAI && currentState == GameState.Playing)
                {
                    // 添加延迟，让用户能看到AI的移动
                    System.Threading.Tasks.Task.Delay(500).ContinueWith(_ => StartAITurn());
                }
            }

            // 触发AI移动完成事件
            AIMoveCompleted?.Invoke(this, e);
        }

        #endregion
    }

    /// <summary>
    /// 移动记录
    /// </summary>
    public class Move
    {
        public int Row { get; set; }
        public int Col { get; set; }
        public PieceType PieceType { get; set; }

        public Move(int row, int col, PieceType pieceType)
        {
            Row = row;
            Col = col;
            PieceType = pieceType;
        }
    }

    /// <summary>
    /// 游戏事件参数
    /// </summary>
    public class GameEventArgs : EventArgs
    {
        public GameState GameState { get; set; }
    }

    /// <summary>
    /// 移动事件参数
    /// </summary>
    public class MoveEventArgs : EventArgs
    {
        public Move Move { get; set; }
    }

    /// <summary>
    /// 玩家切换事件参数
    /// </summary>
    public class PlayerChangedEventArgs : EventArgs
    {
        public PieceType CurrentPlayer { get; set; }
    }
} 